1use super::super::script::ReadParam;
2use super::base::CustomOps;
3use crate::ext::io::*;
4use anyhow::Result;
5use int_enum::IntEnum;
6use std::collections::HashMap;
7use std::io::Seek;
8
9#[repr(u8)]
10#[derive(Debug, IntEnum)]
11enum HanaouOp {
12 End = 0x22,
13 Jump,
14 Call,
15 AutoPlay,
16 Frame,
17 Text,
18 Clear,
19 Gap,
20 Mes,
21 Tlk,
22 Menu,
23 Select,
24 LsfInit,
25 LsfSet,
26 Cg,
27 Em,
28 Clr,
29 Disp,
30 Path,
31 Trans,
32 BgmPlay,
33 BgmStop,
34 BgmVolume,
35 BgmFx,
36 AmbPlay,
37 AmbStop,
38 AmbVolume,
39 AmbFx,
40 SePlay,
41 SeStop,
42 SeWait,
43 SeVolume,
44 SeFx,
45 VocPlay,
46 VocStop,
47 VocWait,
48 VocVolume,
49 VocFx,
50 Quake,
51 Flash,
52 Filter,
53 Effect,
54 Sync,
55 Wait,
56 Movie,
57 Credit,
58 Event,
59 Scene,
60 Title,
61 Notice,
62 Info,
63 SetPass,
64 IsPass,
65 AutoSave,
66 Place,
67 OpenName,
68 Name,
69 LogNew,
70 LogOut,
71 ElapsedDays,
72 Date,
73 TimeTable,
74 Lesson,
75 LessonExp,
76 QuestAdd,
77 QuestDel,
78 QuestMenu,
79 QuestExp,
80 MasterExp,
81 Battle,
82 Status,
83 Tutorial,
84 SetMaster,
85 GetMaster,
86 SetPlayer,
87 GetPlayer,
88 SetQuest,
89 GetQuest,
90 AddSkill,
91 HasSkill,
92 SetDesk,
93 GetLesson,
94 Impact,
95}
96
97#[derive(Debug)]
98pub struct HanaouOps<T: std::fmt::Debug + std::hash::Hash> {
99 prev_name: Option<T>,
100 menus: HashMap<T, T>,
101 last_select: usize,
102}
103
104impl<T: std::fmt::Debug + std::hash::Hash> HanaouOps<T> {
105 pub fn new() -> Self {
106 Self {
107 prev_name: None,
108 menus: HashMap::new(),
109 last_select: 0,
110 }
111 }
112}
113
114use HanaouOp::*;
115
116impl<T> CustomOps<T> for HanaouOps<T>
117where
118 T: std::fmt::Debug + TryInto<u64> + std::hash::Hash,
119{
120 fn run<'a>(&mut self, vm: &mut super::super::script::VM<'a, T>, op: u8) -> Result<bool>
121 where
122 MemReaderRef<'a>: ReadParam<T>,
123 T: TryInto<u64>
124 + Default
125 + Eq
126 + Ord
127 + Copy
128 + std::fmt::Debug
129 + std::fmt::Display
130 + std::hash::Hash
131 + From<u8>
132 + std::ops::Neg<Output = T>
133 + std::ops::Add<Output = T>
134 + std::ops::Sub<Output = T>
135 + std::ops::Mul<Output = T>
136 + std::ops::Div<Output = T>
137 + std::ops::Rem<Output = T>
138 + std::ops::Not<Output = T>
139 + std::ops::BitAnd<Output = T>
140 + std::ops::BitOr<Output = T>
141 + std::ops::BitXor<Output = T>
142 + std::ops::Shr<Output = T>
143 + std::ops::Shl<Output = T>,
144 anyhow::Error: From<<T as TryInto<u64>>::Error>,
145 {
146 if let Ok(op) = HanaouOp::try_from(op) {
147 match op {
148 End => vm.skip_n_params(1, false),
149 Jump => vm.skip_n_params(1, false),
150 Call => vm.skip_n_params(1, false),
151 AutoPlay => vm.skip_n_params(1, false),
152 Frame => vm.skip_n_params(1, false),
153 Text => vm.skip_n_params(2, false),
154 Clear => vm.skip_n_params(1, false),
155 Gap => vm.skip_n_params(2, false),
156 Mes => {
158 let params = vm.read_params(Some(1))?;
159 let mes = params[0];
160 vm.mess.insert(mes);
161 if let Some(name) = self.prev_name.take() {
162 vm.names.insert(mes, name);
163 }
164 Ok(false)
165 }
166 Tlk => {
167 let params = vm.read_params(None)?;
168 let name = params
169 .get(0)
170 .cloned()
171 .ok_or(anyhow::anyhow!("Missing name parameter"))?;
172 self.prev_name = Some(name);
173 Ok(false)
174 }
175 Menu => {
176 let params = vm.read_params(Some(3))?;
177 let id = params[0];
178 let mes = params[1];
179 vm.mess.insert(mes);
180 self.menus.insert(id, mes);
181 Ok(false)
182 }
183 Select => {
184 let param = vm.read_params(Some(1))?;
185 println!("Select param: {:?}", param);
186 if let Some(var) = vm.vars.get_mut(&T::from(131)) {
187 *var = *var + T::from(1);
188 return Ok(false);
189 }
190 let offset = vm.reader.stream_position()? - 1;
191 for _ in self.last_select + 1..self.menus.len() {
192 vm.stack.push(offset);
193 }
195 vm.vars.insert(T::from(131), T::from(0));
196 Ok(false)
197 }
198 LsfInit => vm.skip_n_params(1, false),
199 LsfSet => vm.skip_params(false),
200 Cg => vm.skip_params(false),
201 Em => vm.skip_n_params(5, false),
202 Clr => vm.skip_n_params(1, false),
203 Disp => vm.skip_n_params(3, false),
204 Path => vm.skip_params(false),
205 Trans => Ok(false),
206 BgmPlay => vm.skip_n_params(3, false),
207 BgmStop => vm.skip_n_params(1, false),
208 BgmVolume => vm.skip_n_params(2, false),
209 BgmFx => vm.skip_n_params(1, false),
210 AmbPlay => vm.skip_n_params(3, false),
211 AmbStop => vm.skip_n_params(1, false),
212 AmbVolume => vm.skip_n_params(2, false),
213 AmbFx => vm.skip_n_params(1, false),
214 SePlay => vm.skip_n_params(5, false),
215 SeStop => vm.skip_n_params(2, false),
216 SeWait => vm.skip_n_params(1, false),
217 SeVolume => vm.skip_n_params(3, false),
218 SeFx => vm.skip_n_params(1, false),
219 VocPlay => vm.skip_n_params(4, false),
220 VocStop => vm.skip_n_params(2, false),
221 VocWait => vm.skip_n_params(1, false),
222 VocVolume => vm.skip_n_params(3, false),
223 VocFx => vm.skip_n_params(1, false),
224 Quake => vm.skip_n_params(4, false),
225 Flash => vm.skip_n_params(2, false),
226 Filter => vm.skip_n_params(2, false),
227 Effect => vm.skip_n_params(1, false),
228 Sync => vm.skip_n_params(2, false),
229 Wait => vm.skip_n_params(1, false),
230 Movie => vm.skip_n_params(1, false),
231 Credit => vm.skip_n_params(1, false),
232 Event => vm.skip_n_params(1, false),
233 Scene => vm.skip_n_params(1, false),
234 Title => {
235 let title = vm.read_params(Some(1))?;
236 vm.mess.insert(title[0]);
237 Ok(false)
238 }
239 Notice => {
240 let notices = vm.read_params(Some(3))?;
241 vm.mess.insert(notices[0]);
242 Ok(false)
243 }
244 Info => {
245 let infos = vm.read_params(Some(2))?;
246 vm.mess.insert(infos[0]);
247 Ok(false)
248 }
249 SetPass => vm.skip_n_params(2, false),
250 IsPass => vm.skip_n_params(1, false),
251 AutoSave => Ok(false),
252 Place => vm.skip_n_params(1, false),
253 OpenName => vm.skip_n_params(1, false),
254 Name => {
255 let params = vm.read_params(Some(2))?;
256 let name = params[0];
257 let mes = params[1];
258 vm.mess.insert(mes);
259 vm.names.insert(mes, name);
260 Ok(false)
261 }
262 LogNew => vm.skip_n_params(1, false),
263 LogOut => vm.skip_params(false),
264 ElapsedDays => vm.skip_n_params(1, false),
265 Date => Ok(false),
266 TimeTable => vm.skip_n_params(2, false),
267 Lesson => vm.skip_n_params(1, false),
268 LessonExp => vm.skip_n_params(2, false),
269 QuestAdd => vm.skip_n_params(1, false),
270 QuestDel => vm.skip_n_params(1, false),
271 QuestMenu => Ok(false),
272 QuestExp => vm.skip_n_params(2, false),
273 MasterExp => vm.skip_n_params(2, false),
274 Battle => vm.skip_n_params(3, false),
275 Status => Ok(false),
276 Tutorial => vm.skip_n_params(1, false),
277 SetMaster => vm.skip_n_params(3, false),
278 GetMaster => vm.skip_n_params(2, false),
279 SetPlayer => vm.skip_n_params(2, false),
280 GetPlayer => vm.skip_n_params(1, false),
281 SetQuest => vm.skip_n_params(3, false),
282 GetQuest => vm.skip_n_params(2, false),
283 AddSkill => vm.skip_n_params(2, false),
284 HasSkill => vm.skip_n_params(1, false),
285 SetDesk => vm.skip_n_params(2, false),
286 GetLesson => vm.skip_n_params(3, false),
287 Impact => Ok(false),
288 }
289 } else {
290 Ok(false)
292 }
293 }
294}